﻿using System;
using System.IO;
using System.Web;

namespace Portal.FileSystemData
{
  /// <summary>
  /// Shared Data for directories and files.
  /// </summary>
  public abstract class FileSystemWrapper
  {
    protected DirectoryWrapper _parent;
    protected string _virtualPath;
    protected string _physicalPathRelative;
    protected FileSystemInfo _fileSystemInfo;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="info">The associated FilesSystemInfo</param>
    /// <param name="parent">The Parent Directory</param>
    public FileSystemWrapper(FileSystemInfo info, DirectoryWrapper parent)
    {
      _fileSystemInfo = info;
      _parent = parent;
    }

    /// <summary>
    /// The Physical Name of the entry.
    /// </summary>
    public virtual string Name
    {
      get { return _fileSystemInfo.Name; }
      set 
      {
        if (_fileSystemInfo.Name != value)
        {
          RenameTo(value);
          _virtualPath = null;
          _physicalPathRelative = null;
        }
      }
    }

    /// <summary>
    /// Renames the item.
    /// </summary>
    /// <param name="newName">The new name</param>
    protected abstract void RenameTo(string newName);

    /// <summary>
    /// The parent directory.
    /// </summary>
    public DirectoryWrapper Parent
    {
      get { return _parent; }
    }


    /// <summary>
    /// The absolute physical path to this item.
    /// </summary>
    public string PhysicalPath
    {
      get
      {
        return _fileSystemInfo.FullName;
      }
    }

    /// <summary>
    /// The relative physical path to this item.
    /// </summary>
    public string PhysicalPathRelative
    {
      get
      {
        // Only build the path the first time or after a change.
        if (_physicalPathRelative == null)
        {
          if (_parent == null)
          {
            _physicalPathRelative = "";
          }
          else
          {
            string parentPath = Parent.VirtualPath;
            if (string.IsNullOrEmpty(parentPath))
              _physicalPathRelative = Name;
            else
              _physicalPathRelative = Path.Combine(parentPath, Name);
          }
        }
        return _physicalPathRelative;
      }
    }

    /// <summary>
    /// The relative virtual path to this item.
    /// </summary>
    public virtual string VirtualPath
    {
      get
      {
        // Only build the path the first time or after a change.
        if(_virtualPath == null)
        {
          if (_parent == null)
          {
            _virtualPath = "";
          }
          else
          {
            string parentPath = Parent.VirtualPath;
            if (string.IsNullOrEmpty(parentPath))
              _virtualPath = Name;
            else
              _virtualPath = parentPath + Name;
          }
        }
        return _virtualPath;
      }
    }

    /// <summary>
    /// The physical item information.
    /// </summary>
    public FileSystemInfo FileInfo
    {
      get { return _fileSystemInfo; }
    }

    /// <summary>
    /// The caption for displaying in user interfaces.
    /// </summary>
    public abstract string PresentationName { get; set; }

    /// <summary>
    /// The path for displaying in user interfaces.
    /// </summary>
    /// <param name="delimiter">The delimiter between the path parts.</param>
    public string GetPresentationPath(string delimiter)
    {
      string path = "";
      if (_parent != null)
        path = _parent.GetPresentationPath(delimiter) + delimiter;
      path += PresentationName;
      return path;
    }

    /// <summary>
    /// The string to use as tooltip for the item.
    /// </summary>
    public abstract string Tooltip { get; set; }

    /// <summary>
    /// The string to use as description for the item.
    /// </summary>
    public abstract string Description { get; set; }

    /// <summary>
    /// Is this item a directory?
    /// </summary>
    public abstract bool IsDirectory { get; }

    /// <summary>
    /// The modification date of the file.
    /// </summary>
    public virtual DateTime ModificationDate
    {
      get
      {
        return _fileSystemInfo.LastWriteTime;
      }
      set
      {
        throw new InvalidOperationException();
      }
    }
  }
}